﻿using System;
using System.Collections.Generic;
using System.Linq;
using TaiwuModFramework.Common.Abstract;
using TaiwuModFramework.Common.Base;
using TaiwuModFramework.Common.Info;
using TaiwuModFramework.Common.Utils;

namespace TaiwuModFramework.Common.Manager {
    public class ConfigManager {

        // modIdStr --> (typeAndKey , [item1, item2, item3...])
        private static readonly Dictionary<string, Drawer<string, ConfigItemInfo>> AllModItems = new Dictionary<string, Drawer<string, ConfigItemInfo>>();
        //private static readonly Drawer<string, ConfigItemInfo> AllModItems = new Drawer<string, ConfigItemInfo>()



        public static ALogger Log { get { return AFwDomain.Log; }} 

        public static void AddItems(string modIdStr, BaseTaiwuComp comp) {
            if(comp == null) return;
            var items = comp.GetConfigItemInfoList();
            if(!AllModItems.ContainsKey(modIdStr)) {
                AllModItems.Add(modIdStr, new Drawer<string, ConfigItemInfo>());
            }
            var table = AllModItems[modIdStr];
            foreach(var item in items) {
                table.Add(item.TypeAndKey, item);
            }
        }
        public static void AddItems(string modIdStr, IEnumerable<BaseTaiwuComp> comps) {
            if(comps == null) return;
            foreach(var comp in comps) {
                AddItems(modIdStr, comp);
            }
        }



        public static void UpdateItem(string modIdStr, Type type, string configItemKey, object value) {
            if(type != value.GetType()) throw new Exception("提供的值与类型不匹配");
            var key = ConfigItemInfo.CalcKey(type, configItemKey);                      // 计算在容器中存放的key
            UpdateItem(modIdStr, key, value);
        }

        /// <summary>
        /// 更新指定的配置项的值
        /// </summary>
        /// <param name="modIdStr">modId</param>
        /// <param name="key">计算后的配置项的Key，包含类型和名称</param>
        /// <param name="value">值</param>
        public static void UpdateItem(string modIdStr, string key, object value) {
            if(!AllModItems.ContainsKey(modIdStr)) return;
            AllModItems[modIdStr].Values(key).ForEach(item => item.Value = value);    // 更新值  
        }

        /// <summary>
        /// 使用配置的Option方法更新mod配置项
        /// </summary>
        /// <param name="modIdStr"></param>
        /// <param name="type"></param>
        /// <param name="configItemKey"></param>
        public static void UpdateItem(string modIdStr, Type type, string configItemKey) {
            
            try {
                var option = AFwDomain.GetItemReader(type);
                if(option == null) return;
                var value = option.Read(modIdStr,configItemKey);
                UpdateItem(modIdStr, type, configItemKey, value);
            } catch(Exception e) {
                Log.Error(e);
            }
        }

        public static void UpdateItem(string modIdStr) {
            if(!AllModItems.ContainsKey(modIdStr)) return;
            var items = AllModItems[modIdStr];
            foreach(var key in items.Keys()) {
                var list = items.Values(key);
                list.ForEach(info => UpdateItem(modIdStr, info.ConfigItemType, info.ConfigItemKey));
            }
        }

        public static void UpdateItem() {
            foreach(var modIdStr in AllModItems.Keys) {
                UpdateItem(modIdStr);
            }
        }


        public static List<string> GetItemKeyByModId(string modIdStr) {
            if(AllModItems.TryGetValue(modIdStr, out Drawer<string, ConfigItemInfo> drawer)) {
                return drawer.Keys().ToList<string>();
            }
            return new List<string>();
        }

        public static object GetItemValue(string modIdStr, Type type, string cofigItemKey) {
            return GetItemValue(modIdStr, ConfigItemInfo.CalcKey(type, cofigItemKey));
        }

        public static object GetItemValue(string modIdStr, string typeAndKey) {
            if(AllModItems.TryGetValue(modIdStr, out Drawer<string, ConfigItemInfo> drawer)) {
                var items = drawer.Values(typeAndKey);
                if(items.Count > 0) {
                    return items[0].Value;
                }
            }
            return null;
        }
    }
}
